//
//  WCExtractArray.m
//  WebClipper
//
//  Created by Daniel Braun on 04/04/07.
//  Copyright 2007 Daniel Braun http://page-appart.net, http://braun.daniel.free.fr All rights reserved.
//

#import "WCExtractArray.h"
#import "DomExtension.h"

@implementation WCExtractArray

+ (NSString *) description
{
	return @"array";
}

- (void) dealloc {
	[cachedContent release];
	[super dealloc];
}

- (id) init {
	self = [super init];
	if (self != nil) {
		kind=0;
	}
	return self;
}

- (id) initWithCoder:(NSCoder *) coder
{
	self=[super initWithCoder:coder];
	if ([coder allowsKeyedCoding]) {
		kind=[coder decodeIntForKey:@"kind"];
		outputFormat=[coder decodeIntForKey:@"outputFormat"];
		allowLevelChange=[coder decodeIntForKey:@"allowLevelChange"];
	}
	return self;
}

- (void)encodeWithCoder:(NSCoder *)coder
{
	[super encodeWithCoder:coder];
	if ( [coder allowsKeyedCoding] ) {
		[coder encodeInt:kind forKey:@"kind"];
		[coder encodeInt:outputFormat forKey:@"outputFormat"];
		[coder encodeInt:allowLevelChange forKey:@"allowLevelChange"];

	}
}

- (int) kind
{
	return kind;
}
- (void) setKind:(int)n
{
	kind=n;
}

static DOMNode *nextItem(DOMNode *el, NSString *itt, int maxlev, int *plev, BOOL first, NSMutableArray *stack)
{
	NSString *v=[[el nodeName]lowercaseString];
	
	if (first && [v isEqualToString:itt]) return el;
	if (maxlev<=0) return nil;
	if (plev) (*plev)++;
	DOMNode *n;
	DOMNode *elr;
	if (![el isKindOfClass:[DOMHTMLElement class]]) return nil;
	
	DOMNode *ns=[el nextSibling];
	for (n=[el firstChild]; n; n=[n nextSibling]) {
		elr=nextItem(n, itt, maxlev-1, plev, true, stack);
		if (elr) {
			if (ns) [stack addObject:ns];
			return elr;
		}
	}
	if (plev) (*plev)--;
	el=[el nextSibling];
	if (!el) return nil;
	return nextItem(el, itt, maxlev, plev, true, stack);
}

- (id) formatForOutput:(DOMHTMLElement *)el
{
	NSString *s;
	//@"html", @"text", @"attr str", @"txt+href", nil
	switch (outputFormat) {
		default:
		case 0: return [super handle:el fromUrl:nil];
		case 1: 
			if ([el respondsToSelector:@selector(innerText)]) {
				return [(id)el innerText];
			} else if ([el respondsToSelector:@selector(nodeValue)]) {
				return [(id)el nodeValue];
			} else if ([el respondsToSelector:@selector(stringValue)]) {
				return [(id)el stringValue];	
			}
			return [super handle:el fromUrl:nil];
		case 2:
			s=[super handle:el fromUrl:nil];
			NSData *d=[s dataUsingEncoding:NSUTF8StringEncoding allowLossyConversion:YES];
			return [[[NSAttributedString alloc]
				  initWithHTML:d
				 documentAttributes:nil]autorelease];
		case 3:
			if ([el respondsToSelector:@selector(innerText)]) {
				s=[(id)el innerText];
			} else if ([el respondsToSelector:@selector(nodeValue)]) {
				s=[(id)el nodeValue];
			} else if ([el respondsToSelector:@selector(stringValue)]) {
				s=[(id)el stringValue];	
			}
			DOMHTMLElement *lnk=(DOMHTMLElement *)[[el getElementsByTagName:@"A"]item:0];
			NSMutableDictionary *tl=[NSMutableDictionary dictionaryWithCapacity:2];
			[tl setObject:s forKey:@"text"];
			NSString *lr=[lnk getAttribute:@"href"];
			if (lr) [tl setObject:lr forKey:@"href"];
			return tl;
	}
}

- (id) handle:(DOMHTMLElement *)el fromUrl:(NSURL *)url
{
	//"list", @"tbl lines", @"tbl cell", @"2x cell", nil]retain];
	NSMutableArray *a=[NSMutableArray arrayWithCapacity:100];
	int i;
	NSMutableArray *stack=[NSMutableArray arrayWithCapacity:5];
	NSString *cellElement=nil;
	BOOL useStack=allowLevelChange;
	switch (kind) {
		default:
		case 0: // list
			cellElement=@"li";
			break;
		case 1: // rows
			cellElement=@"tr";
			break;
		case 2: // cells
			cellElement=@"td";
			useStack=YES;
			break;
		case 3: // bidimentional array
			cellElement=@"tr";
			useStack=NO;
			break;
	}
	if (3==kind) {
		// TODO
	} else {
		for (i=0;;i++) {
			el=(DOMHTMLElement*)nextItem(el, cellElement, 10, NULL, !i, stack);
			if (!el) {
				if (!useStack) break;
				el=[stack lastObject];
				if (!el) break;
				[stack removeLastObject];
				continue;
			}
			NSLog(@"got sv=%@\n", el);
			[a addObject:[self formatForOutput:el]];
		}
	}
	if (0) NSLog(@"got %d elem\n", [a count]);
	return a;
}

- (NSAttributedString *) arrayDisplay
{
	return cachedContent;
}


@end
